<script setup lang="ts">
import { ref, reactive, computed, nextTick, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { useRouter, useRoute } from "vue-router";
import {
  getDiningList,
  addDining,
  editDining,
  deleteDining,
  uploadImage,
  deleteImage,
  getImagesByRecordId,
  type RecordImage
} from "@/api/love/dining";
import dayjs from "dayjs";
import {
  Delete,
  Plus,
  ZoomIn,
  Download,
  UploadFilled
} from "@element-plus/icons-vue";

interface DiningRecord {
  id: number;
  location: string;
  longitude: number;
  latitude: number;
  date: string; // 'YYYY-MM-DD HH:mm'
  amount: number;
  people: string; // 逗号分隔
  type: string;
  images: string[];
}

const typeOptions = ["吃饭", "游玩", "爬山", "吵架", "逛街"];

const records = ref<DiningRecord[]>([]);
const total = ref(0);

const drawerVisible = ref(false);
const newRecord = reactive<DiningRecord>({
  id: 0,
  location: "",
  longitude: 0,
  latitude: 0,
  date: dayjs().format("YYYY-MM-DD HH:mm"),
  amount: 0,
  people: "",
  type: "吃饭",
  images: []
});

const editingRow = ref<number | null>(null);
const originalRowData = ref<DiningRecord | null>(null);

// 搜索相关
const searchLocation = ref("");

const getInitialDateRange = () => {
  return [];
};
const searchDateRange = ref<string[]>(getInitialDateRange());
const searchTrigger = ref(0); // 用于手动触发搜索

const dateShortcuts = [
  {
    text: "近一个月",
    value: () => {
      const end = dayjs();
      const start = dayjs().subtract(1, "month");
      return [start.format("YYYY-MM-DD"), end.format("YYYY-MM-DD")];
    }
  },
  {
    text: "近三个月",
    value: () => {
      const end = dayjs();
      const start = dayjs().subtract(3, "month");
      return [start.format("YYYY-MM-DD"), end.format("YYYY-MM-DD")];
    }
  },
  {
    text: "近半年",
    value: () => {
      const end = dayjs();
      const start = dayjs().subtract(6, "month");
      return [start.format("YYYY-MM-DD"), end.format("YYYY-MM-DD")];
    }
  },
  {
    text: "近一年",
    value: () => {
      const end = dayjs();
      const start = dayjs().subtract(1, "year");
      return [start.format("YYYY-MM-DD"), end.format("YYYY-MM-DD")];
    }
  },
  {
    text: "近三年",
    value: () => {
      const end = dayjs();
      const start = dayjs().subtract(3, "year");
      return [start.format("YYYY-MM-DD"), end.format("YYYY-MM-DD")];
    }
  }
];

// 分页相关
const pageSize = ref(10);
const currentPage = ref(1);

const pagedRecords = computed(() => {
  return records.value;
});

// 地图弹窗相关
const mapDialogVisible = ref(false);
const mapInputValue = ref("");
let map: any = null;
let marker: any = null;
let autoComplete: any = null;
const mapContainerId = "amap-dialog-container";

const router = useRouter();
const route = useRoute();

// 详情弹窗相关
const detailsDialogVisible = ref(false);
const currentRecord = ref<DiningRecord | null>(null);
const managedImages = ref<RecordImage[]>([]);
const isImageManagerLoading = ref(false);
const detailsMapContainerId = "amap-details-container";
let detailsMap: any = null;

const detailsDialogTitle = computed(() => {
  return currentRecord.value ? `${currentRecord.value.type}详情` : "详情";
});

const imageManagerDialogTitle = computed(() => {
  return currentRecord.value
    ? `管理 "${currentRecord.value.location}" 的图片`
    : "图片管理";
});

// 加载用餐记录列表
async function loadDiningList() {
  try {
    const params: any = {
      page: currentPage.value,
      size: pageSize.value
    };
    if (searchLocation.value) params.location = searchLocation.value;
    if (searchDateRange.value && searchDateRange.value.length === 2) {
      params.startDate = searchDateRange.value[0];
      params.endDate = searchDateRange.value[1];
    }
    const data = await getDiningList(params);
    // data.records: 列表, data.total: 总数
    records.value = Array.isArray(data.records) ? data.records : [];
    total.value = data.total || 0;
  } catch (e) {
    records.value = [];
    total.value = 0;
  }
}

onMounted(() => {
  if (route.query.location) {
    searchLocation.value = route.query.location as string;
  }
  loadDiningList();
});

function openAddDrawer() {
  Object.assign(newRecord, {
    id: 0,
    location: "",
    longitude: 0,
    latitude: 0,
    date: dayjs().format("YYYY-MM-DD HH:mm"),
    amount: 0,
    people: "",
    type: "吃饭",
    images: []
  });
  drawerVisible.value = true;
}

function openMapDialog() {
  mapDialogVisible.value = true;
  mapInputValue.value = newRecord.location;
  nextTick(() => {
    initMapDialog();
  });
}

function initMapDialog() {
  if (!window.AMap) return;
  if (map) {
    map.destroy();
    map = null;
  }
  map = new window.AMap.Map(mapContainerId, {
    resizeEnable: true,
    zoom: 12,
    center: [108.95, 34.27]
  });
  marker = null;
  autoComplete = new window.AMap.AutoComplete({ city: "西安" });

  map.on("click", function (e: any) {
    const lnglat = e.lnglat;
    const geocoder = new window.AMap.Geocoder();
    geocoder.getAddress(lnglat, function (status: string, result: any) {
      if (status === "complete" && result.regeocode) {
        setMapLocation(result.regeocode.formattedAddress, lnglat);
      }
    });
  });
}

function fetchMapSuggestions(queryString: string, cb: (arg: any) => void) {
  if (!autoComplete) {
    cb([]);
    return;
  }
  autoComplete.search(queryString, function (status: string, result: any) {
    if (status === "complete" && result.tips) {
      const suggestions = result.tips
        .filter((tip: any) => tip.location)
        .map((tip: any) => ({ ...tip, value: tip.name }));
      cb(suggestions);
    } else {
      cb([]);
    }
  });
}

function onMapInputSelect(item: any) {
  if (!item.location) return;
  mapInputValue.value = item.name;
  setMapLocation(item.name, item.location);
}

function setMapLocation(name: string, location: any) {
  newRecord.location = name;
  newRecord.longitude = location.lng;
  newRecord.latitude = location.lat;

  if (map) {
    map.setCenter([location.lng, location.lat]);
    map.setZoom(16);
    if (marker) marker.setMap(null);
    marker = new window.AMap.Marker({
      map: map,
      position: [location.lng, location.lat]
    });
  }
  ElMessage.success("已选择地点: " + name);
  mapDialogVisible.value = false;
}

function openDetailsDialog(record: DiningRecord) {
  currentRecord.value = record;
  detailsDialogVisible.value = true;
  nextTick(() => {
    initDetailsMap();
  });
}

function initDetailsMap() {
  if (!window.AMap || !currentRecord.value) return;
  if (detailsMap) {
    detailsMap.destroy();
    detailsMap = null;
  }
  const { longitude, latitude } = currentRecord.value;
  detailsMap = new window.AMap.Map(detailsMapContainerId, {
    resizeEnable: true,
    zoom: 16,
    center: [longitude, latitude]
  });
  new window.AMap.Marker({
    map: detailsMap,
    position: [longitude, latitude]
  });
}

async function openImageManagerDialog(record: DiningRecord) {
  currentRecord.value = record;
  detailsDialogVisible.value = true;
  managedImages.value = [];
  try {
    isImageManagerLoading.value = true;
    managedImages.value = await getImagesByRecordId(record.id);
  } catch (e) {
    ElMessage.error("获取图片列表失败");
  } finally {
    isImageManagerLoading.value = false;
  }
}

async function handleDeleteImage(image: RecordImage, imageIndex: number) {
  if (!currentRecord.value) return;

  try {
    await ElMessageBox.confirm(
      "确定要删除这张美美的照片吗？此操作不可恢复！",
      "删除确认",
      {
        confirmButtonText: "确定删除",
        cancelButtonText: "我再想想",
        type: "warning"
      }
    );

    await deleteImage(image.id);

    managedImages.value.splice(imageIndex, 1);
    // 更新表格中的图片数量
    const urlToDelete = image.imageUrl;
    const indexInRow = currentRecord.value.images.indexOf(urlToDelete);
    if (indexInRow > -1) {
      currentRecord.value.images.splice(indexInRow, 1);
    }
    ElMessage.success("照片已删除");
  } catch (error) {
    if (error !== "cancel") {
      ElMessage.error("删除失败，请稍后重试");
    }
  }
}

function addRecord() {
  if (!newRecord.location || !newRecord.date || !newRecord.people) {
    ElMessage.warning("请填写完整信息");
    return;
  }
  // 新增时不传id
  const { id, ...postData } = newRecord;
  // images字段保证为数组
  postData.images = Array.isArray(newRecord.images) ? newRecord.images : [];
  addDining(postData)
    .then(() => {
      drawerVisible.value = false;
      ElMessage.success("新增成功");
      loadDiningList();
      nextTick(() => {
        currentPage.value = 1;
      });
    })
    .catch(() => {});
}

function deleteRecord(row: DiningRecord) {
  ElMessageBox.confirm("确定要删除这条用餐记录吗？", "提示", {
    type: "warning"
  })
    .then(() => {
      deleteDining(row.id)
        .then(() => {
          ElMessage.success("删除成功");
          loadDiningList();
        })
        .catch(() => {});
    })
    .catch(() => {});
}

function handleRowDblClick(row: DiningRecord) {
  // If another row is being edited, just save it before starting to edit the new one.
  if (editingRow.value !== null) {
    const currentlyEditingRow = records.value.find(
      r => r.id === editingRow.value
    );
    if (currentlyEditingRow) {
      saveEdit(currentlyEditingRow);
    }
  }
  originalRowData.value = { ...row };
  editingRow.value = row.id;
}

function saveEdit(row: DiningRecord) {
  const { id, ...putData } = row;
  putData.images = Array.isArray(row.images) ? row.images : [];
  editDining(row.id, putData)
    .then(() => {
      editingRow.value = null;
      originalRowData.value = null;
      ElMessage.success("修改成功");
      loadDiningList();
    })
    .catch(() => {});
}

function cancelEdit(row: DiningRecord) {
  if (originalRowData.value) {
    Object.assign(row, originalRowData.value);
  }
  editingRow.value = null;
  originalRowData.value = null;
}

function handleInputEnter(row: DiningRecord) {
  saveEdit(row);
}

function resetSearch() {
  searchLocation.value = "";
  searchDateRange.value = getInitialDateRange();
  searchTrigger.value++;
  loadDiningList();
}

function doSearch() {
  searchTrigger.value++;
  currentPage.value = 1;
  loadDiningList();
}

function handlePageChange(val: number) {
  currentPage.value = val;
  loadDiningList();
}

function handleTypeChange(row: DiningRecord, val: string) {
  if (val.length > 5) {
    ElMessage.warning("类型最多5个字");
    row.type = val.slice(0, 5);
  }
}

function getTypeTagType(type: string) {
  switch (type) {
    case "吃饭":
      return "success";
    case "游玩":
      return "primary";
    case "爬山":
      return "warning";
    case "吵架":
      return "danger";
    case "逛街":
      return "info";
    default:
      return "info";
  }
}

/**
 * 防抖函数
 * @param func 要执行的函数
 * @param wait 等待时间（毫秒）
 */
function debounce(func: Function, wait: number) {
  let timeout: any;
  return function (this: any, ...args: any[]) {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}

let uploadSuccessCount = 0;
let uploadStartTime = 0;
const resetUploadCount = debounce(() => {
  uploadSuccessCount = 0;
}, 2000);

const showUploadSuccessMessage = debounce(() => {
  if (uploadSuccessCount > 0) {
    ElMessage.success(`已成功上传 ${uploadSuccessCount} 张美美哒的照片`);
    resetUploadCount();
  }
}, 500);

// 处理多文件上传
async function handleFilesUpload(row: DiningRecord, files: File[]) {
  if (!row.id) {
    ElMessage.error("请先保存记录再上传图片");
    return;
  }

  if (files.length === 0) return;

  // 记录开始上传的时间，用于分组上传
  if (Date.now() - uploadStartTime > 2000) {
    uploadSuccessCount = 0;
    uploadStartTime = Date.now();
  }

  try {
    const res = await uploadImage(row.id, files);
    if (!row.images) row.images = [];
    if (Array.isArray(res)) {
      const newUrls = res.map((img: any) => img.url).filter(Boolean);
      row.images.push(...newUrls);
      uploadSuccessCount += newUrls.length;
    } else if (res && res.url) {
      row.images.push(res.url);
      uploadSuccessCount++;
    }
    showUploadSuccessMessage();
  } catch (e) {
    ElMessage.error(`上传失败，请稍后重试`);
  }
}

// 处理上传请求
async function customHttpRequest(row: DiningRecord, options: any) {
  const { file } = options;
  try {
    await handleFilesUpload(row, [file]);
    options.onSuccess();
  } catch (e) {
    options.onError(new Error("上传失败"));
  }
}

function handleImageRemove(row: DiningRecord, idx: number) {
  if (row.images) row.images.splice(idx, 1);
}

function goToDetails(row: DiningRecord) {
  router.push({
    name: "LoveDiningDetail",
    params: { id: row.id }
  });
}

function handleBeforeUpload(file: File) {
  // Implementation of handleBeforeUpload
}

function handleBatchUpload(row, fileList) {
  if (!row.id) {
    ElMessage.error("请先保存记录再上传图片");
    return;
  }
  if (!fileList.length) return;
  const formData = new FormData();
  fileList.forEach(f => formData.append("files", f.raw));
  fetch(`/love/upload/${row.id}`, {
    method: "POST",
    body: formData
  })
    .then(r => r.json())
    .then(res => {
      if (res && Array.isArray(res.data)) {
        ElMessage.success(`已成功上传 ${res.data.length} 张照片`);
      }
    })
    .catch(() => ElMessage.error("上传失败"));
}
</script>

<template>
  <div class="dining-page">
    <el-card shadow="never" class="mb-4">
      <div class="search-add-wrapper">
        <div class="search-bar">
          <el-input
            v-model="searchLocation"
            placeholder="按地点搜索"
            clearable
            style="width: 200px"
          />
          <el-date-picker
            v-model="searchDateRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="YYYY-MM-DD"
            :shortcuts="dateShortcuts"
            style="width: 320px; flex: none"
          />
          <el-button type="primary" @click="doSearch">搜索</el-button>
          <el-button @click="resetSearch">重置</el-button>
        </div>
        <div>
          <el-button type="primary" @click="openAddDrawer">添加</el-button>
        </div>
      </div>
    </el-card>
    <el-card shadow="never">
      <el-table
        :data="pagedRecords"
        border
        style="width: 100%; margin-bottom: 16px"
        @row-dblclick="handleRowDblClick"
      >
        <el-table-column label="序号" type="index" width="60" />
        <el-table-column label="记录类型" prop="type" width="120">
          <template #default="{ row }">
            <template v-if="editingRow === row.id">
              <el-select
                v-model="row.type"
                filterable
                allow-create
                default-first-option
                style="width: 90px"
                @change="val => handleTypeChange(row, val)"
              >
                <el-option
                  v-for="item in typeOptions"
                  :key="item"
                  :label="item"
                  :value="item"
                />
              </el-select>
            </template>
            <template v-else>
              <el-tag :type="getTypeTagType(row.type)">{{ row.type }}</el-tag>
            </template>
          </template>
        </el-table-column>
        <el-table-column label="图片数量" prop="imagesCount" width="100">
          <template #default="{ row }">
            <el-button
              v-if="row.images && row.images.length > 0"
              type="primary"
              link
              @click="openImageManagerDialog(row)"
            >
              {{ row.images.length }} 张
            </el-button>
            <span v-else>—</span>
          </template>
        </el-table-column>
        <el-table-column label="地点" prop="location">
          <template #default="{ row }">
            <template v-if="editingRow === row.id">
              <el-input
                :id="`edit-input-location-${row.id}`"
                v-model="row.location"
                size="small"
              />
            </template>
            <template v-else>
              <el-tooltip :content="row.location" placement="top" effect="dark">
                <div
                  style="
                    white-space: nowrap;
                    overflow: hidden;
                    text-overflow: ellipsis;
                  "
                >
                  {{ row.location }}
                </div>
              </el-tooltip>
            </template>
          </template>
        </el-table-column>
        <el-table-column label="时间" prop="date" width="220">
          <template #default="{ row }">
            <template v-if="editingRow === row.id">
              <el-date-picker
                v-model="row.date"
                type="datetime"
                size="small"
                value-format="YYYY-MM-DD HH:mm"
                placeholder="选择日期时间"
                style="width: 100%"
              />
            </template>
            <template v-else>
              {{ row.date }}
            </template>
          </template>
        </el-table-column>
        <el-table-column label="消费金额" prop="amount">
          <template #default="{ row }">
            <template v-if="editingRow === row.id">
              <el-input-number v-model="row.amount" size="small" :min="0" />
            </template>
            <template v-else>
              {{ row.amount }}
            </template>
          </template>
        </el-table-column>
        <el-table-column label="人员" prop="people">
          <template #default="{ row }">
            <template v-if="editingRow === row.id">
              <el-input v-model="row.people" size="small" />
            </template>
            <template v-else>
              {{ row.people }}
            </template>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="260">
          <template #default="{ row }">
            <template v-if="editingRow === row.id">
              <el-button type="success" size="small" @click="saveEdit(row)"
                >保存</el-button
              >
              <el-button size="small" @click="cancelEdit(row)">取消</el-button>
            </template>
            <template v-else>
              <el-button type="primary" size="small" @click="goToDetails(row)"
                >详情</el-button
              >
              <el-button type="danger" size="small" @click="deleteRecord(row)"
                >删除</el-button
              >
            </template>
          </template>
        </el-table-column>
      </el-table>
      <div style="margin: 16px 0; text-align: right">
        <el-pagination
          background
          layout="prev, pager, next, jumper, total"
          :total="total"
          :page-size="pageSize"
          :current-page="currentPage"
          @current-change="handlePageChange"
        />
      </div>
    </el-card>
    <el-drawer
      v-model="drawerVisible"
      title="添加用餐记录"
      direction="rtl"
      size="600px"
    >
      <el-form label-width="70px">
        <el-form-item label="地点">
          <el-input
            v-model="newRecord.location"
            placeholder="点击选择地点"
            readonly
            style="cursor: pointer; background: #f5f7fa"
            @click="openMapDialog"
          />
        </el-form-item>
        <el-form-item label="时间">
          <el-date-picker
            v-model="newRecord.date"
            type="datetime"
            placeholder="选择用餐时间"
            value-format="YYYY-MM-DD HH:mm"
            style="width: 100%"
          />
        </el-form-item>
        <el-form-item label="金额">
          <el-input-number v-model="newRecord.amount" :min="0" />
        </el-form-item>
        <el-form-item label="人员">
          <el-input v-model="newRecord.people" placeholder="如 小明,小红" />
        </el-form-item>
        <el-form-item label="类型">
          <el-select
            v-model="newRecord.type"
            filterable
            allow-create
            default-first-option
            style="width: 100%"
            @change="
              val => {
                if (val.length > 5) {
                  ElMessage.warning('类型最多5个字');
                  newRecord.type = val.slice(0, 5);
                }
              }
            "
          >
            <el-option
              v-for="item in typeOptions"
              :key="item"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="drawerVisible = false">取消</el-button>
        <el-button type="primary" @click="addRecord">确定</el-button>
      </template>
    </el-drawer>
    <el-dialog
      v-model="mapDialogVisible"
      title="选择地点"
      width="800px"
      top="5vh"
      append-to-body
    >
      <div
        style="
          margin-bottom: 12px;
          display: flex;
          flex-direction: column;
          align-items: flex-start;
        "
      >
        <el-autocomplete
          v-model="mapInputValue"
          :fetch-suggestions="fetchMapSuggestions"
          placeholder="输入关键字搜索地点"
          style="width: 400px; margin-bottom: 8px"
          :trigger-on-focus="false"
          :debounce="300"
          :highlight-first-item="true"
          @select="onMapInputSelect"
        >
          <template #default="{ item }">
            <div style="line-height: 1.2">
              <div style="font-weight: 500">{{ item.name }}</div>
              <span style="font-size: 13px; color: #999">{{
                item.address
              }}</span>
            </div>
          </template>
        </el-autocomplete>
        <div
          :id="mapContainerId"
          style="
            width: 100%;
            height: 400px;
            border: 1px solid #eee;
            border-radius: 4px;
          "
        />
        <div style="margin-top: 8px; color: #888; font-size: 13px">
          可输入关键字自动提示，也可直接点击地图选点
        </div>
      </div>
      <template #footer>
        <el-button @click="mapDialogVisible = false">取消</el-button>
      </template>
    </el-dialog>
    <el-dialog
      v-model="detailsDialogVisible"
      :title="imageManagerDialogTitle"
      width="800px"
      top="5vh"
    >
      <div v-if="currentRecord" v-loading="isImageManagerLoading">
        <div v-if="managedImages.length > 0" class="image-gallery-with-delete">
          <div
            v-for="(img, idx) in managedImages"
            :key="img.id"
            class="image-container"
          >
            <el-image
              :src="img.imageUrl"
              style="width: 150px; height: 150px; border-radius: 8px"
              fit="cover"
              :preview-src-list="managedImages.map(i => i.imageUrl)"
              :initial-index="idx"
            />
            <div class="image-overlay">
              <el-icon class="action-icon" size="30"><ZoomIn /></el-icon>
              <el-icon
                class="action-icon delete-icon"
                size="24"
                @click.stop="handleDeleteImage(img, idx)"
              >
                <Delete />
              </el-icon>
            </div>
          </div>
        </div>
        <el-empty
          v-else-if="!isImageManagerLoading"
          description="暂无图片，快去上传吧！"
        />
      </div>
      <template #footer>
        <el-button @click="detailsDialogVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.dining-page {
  padding: 12px 8px 0 8px;
}
.el-card + .el-card {
  margin-top: 16px;
}
.search-add-wrapper {
  /* Reverted to default block stacking */
}
.search-bar {
  display: flex;
  gap: 16px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.image-gallery-with-delete {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}
.image-container {
  position: relative;
  width: 150px;
  height: 150px;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
}
.image-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  opacity: 0;
  transition: opacity 0.3s ease;
  /* Let clicks pass through to the underlying el-image for preview */
  pointer-events: none;
}
.image-container:hover .image-overlay {
  opacity: 1;
}
.action-icon {
  color: white;
}
.delete-icon {
  /* This icon should be clickable */
  pointer-events: auto;
  position: absolute;
  top: 8px;
  right: 8px;
  cursor: pointer;
}
</style>
